#include "disp_task.h"
#include <ctimer.h>
#include <etimer.h>
#include <process.h>
#include "device_manage.h"
#include "lib/list.h"
#include "memb.h"

#include <stdlib.h>
#include <string.h>
#include "74hc595.h"
#include "fifo.h"
#include "lora_task.h"
#include "stm32f1xx_hal.h"
#include "time.h"
#include "tm1804.h"
#include "uart.h"
#include "voice_task.h"

uint8_t led_data[] = {0x0, 0x0, 0x0, 0x00, 0x00};  //数码管显示
extern uint8_t menu_index;
extern sEnterMenu entermenu;

static tListNum* Slave_Cur;  //当前显示的呼叫器number
uint16_t disp_num_cur;

LIST(dispnum_list);  //显示号码列表
MEMB(m_dispnum, tListDispNum, 32);
static tListDispNum* dispnum = NULL;

uint8_t led = Led_None;  //氛围灯


enum {
  disp_none_num = 0,
  disp_call_num,
  disp_nocall_num,
};

uint8_t dispnum_flag = disp_none_num;

const TMRGB RGB_None[4] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const TMRGB RGB_Init[4] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                           0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const TMRGB RGB_DevWifi[4] = {0x00, 0xaa, 0xaa, 0x00, 0xaa, 0xaa,
                              0x00, 0xaa, 0xaa, 0x00, 0xaa, 0xaa};
const TMRGB RGB_DevGsm[4] = {0xaa, 0x00, 0xaa, 0xaa, 0x00, 0xaa,
                             0xaa, 0x00, 0xaa, 0xaa, 0x00, 0xaa};
const TMRGB RGB_DevSingle[4] = {0xaa, 0xaa, 0x00, 0xaa, 0xaa, 0x00,
                                0xaa, 0xaa, 0x00, 0xaa, 0xaa, 0x00};
const TMRGB RGB_Call[4] = {0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
                           0x00, 0xff, 0x00, 0x00, 0xff, 0x00};
const TMRGB RGB_ClearCall[4] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                                0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const TMRGB RGB_SetOk[4] = {0x55, 0xff, 0x55, 0x55, 0xff, 0x55,
                            0x55, 0xff, 0x55, 0x55, 0xff, 0x55};
const TMRGB RGB_SetNet[4] = {0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
                                   0x00, 0x00, 0xff, 0x00, 0x00, 0xff};
const TMRGB RGB_SetNetOk[4] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};


struct ctimer c_disconnect;  // 网络未连接定时器
static uint8_t disconn_disp_flag = 0;

/**
 * @brief  显示号码内存初始化
 * @note
 * @retval None
 */
void memb_dispnum_init(void) { memb_init(&m_dispnum); }

/**
 * @brief  添加显示号码到list尾
 * @note
 * @param  dispnum: 显示号码
 * @retval None
 */
void add_dispnum(tListDispNum* dispnum) { list_add(dispnum_list, dispnum); }

/**
 * @brief  添加显示号码到list头
 * @note
 * @param  dispnum:
 * @retval None
 */
void push_dispnum(tListDispNum* dispnum) { list_push(dispnum_list, dispnum); }

/**
 * @brief  在list中查找num，找到后移除
 * @note
 * @param  num: 显示号码
 * @retval 1：存在；0：不存在
 */
uint8_t remove_find_dispnum(uint16_t num) {
  tListDispNum* dis_num;

  for (dis_num = list_head(dispnum_list); dis_num != NULL;
       dis_num = dis_num->next) {
    if (dis_num->slave.Val == num) {
      list_remove(dispnum_list, dis_num);
      return 1;
    }
  }
  return 0;
}

/**
 * @brief  在list中查找num
 * @note
 * @param  num:显示号码
 * @retval 1：存在；0：不存在
 */
uint8_t find_dispnum(uint16_t num) {
  tListDispNum* dis_num;

  for (dis_num = list_head(dispnum_list); dis_num != NULL;
       dis_num = dis_num->next) {
    if (dis_num->slave.Val == num) {
      return 1;
    }
  }
  return 0;
}

/**
 * @brief  申请显示号码内存
 * @note
 * @retval 返回申请内存地址
 */
tListDispNum* memb_dispnum_alloc(void) {
  tListDispNum* disp_num = (tListDispNum*)memb_alloc(&m_dispnum);
  return disp_num;
}

/**
 * @brief  释放显示号码内存地址
 * @note
 * @param  ptr: 显示号码地址
 * @retval None
 */
void memb_dispnum_free(void* ptr) { memb_free(&m_dispnum, ptr); }

/**
 * @brief  获取显示列表中num的数量
 * @note
 * @retval num数量
 */
uint8_t get_dispnum_cnt(void) { return list_length(dispnum_list); }

/**
 * @brief  获取list头的num
 * @note
 * @retval None
 */
void* get_dispnum(void) { return list_pop(dispnum_list); }

void menb_dispnum_debug(char* fun) {
  printf("%s m_dispnum mem -> %d,list_len->%d\r\n", fun,
         memb_numfree(&m_dispnum), get_dispnum_cnt());
}
/**
 * @brief  删除所有显示号码
 * @note
 * @retval None
 */
void remove_dispnum_all(void) {
  tListDispNum* dis_num;

  while (get_dispnum_cnt() > 0) {
    for (dis_num = list_head(dispnum_list); dis_num != NULL;
         dis_num = dis_num->next) {
      list_remove(dispnum_list, dis_num);
      memb_dispnum_free(dis_num);
    }
  }
}

/**
 * @brief  删除指定显示号码
 * @note
 * @param  num: 显示号码
 * @retval None
 */
uint8_t remove_dispnum(uint16_t num) {
  tListDispNum* listnum;

  for (listnum = list_head(dispnum_list); listnum != NULL;
       listnum = listnum->next) {
    if (listnum->slave.Val == num) {
      list_remove(dispnum_list, listnum);
      memb_dispnum_free(listnum);
      return 1;
    }
  }
  return 0;
}

void disp_off(void) {
  for (uint8_t i = 0; i < sizeof(led_data); i++) {
    led_data[i] = 0x00;
  }
}

void Disp_Handle(void) {
  static uint8_t bit = 0;
  static uint8_t index = 0;

  bit = 0x01 << index;
  if (bit == 0x01) {
    if (led_data[4] == 0xff) {
      bit |= 0x10;
    } else {
      bit |= 0x70;
    }
  } else {
    bit = bit | 0x60;
  }
  HC595_DisPlayBit(bit, 0);
  HC595_DisPlayBit(bit, led_data[index]);
  ++index;
  index = index % 4;
}

void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef* hrtc) {
  static sLEDData led_data;
  static TIMEDATE_TypeDef htimedate = {0};

  TimeDate_CountTime(&htimedate);
  led_data.cmd = disp_time;
  led_data.led[0] = NumDis[htimedate.Hours % 100 / 10];
  led_data.led[1] = NumDis[htimedate.Hours % 10 / 1];
  led_data.led[2] = NumDis[htimedate.Minutes % 100 / 10];
  led_data.led[3] = NumDis[htimedate.Minutes % 10 / 1];
  led_data.led[4] = ~led_data.led[4];
  led_data.count = 1;
  process_post(&Disp_Process, PROCESS_EVENT_MSG, (process_data_t)&led_data);
}

PROCESS(Disp_Process, "Display");
PROCESS_THREAD(Disp_Process, ev, data) {
  static sLEDData smg_data_now;
  static sLEDData smg_data;
  static sLEDData smg_data_pre;
  static struct etimer et;
  static uint8_t twinkle = 0;

  PROCESS_BEGIN();

  smg_data_pre.cmd = dispcmd_none;
  smg_data_pre.count = 0;
  list_init(dispnum_list);
  memb_dispnum_init();

  while (1) {
    PROCESS_WAIT_EVENT();
    if (ev == PROCESS_EVENT_MSG) {
      smg_data_now = *(sLEDData*)data;
      if (smg_data_pre.cmd == dispcmd_none ||
          smg_data_now.cmd !=
              disp_time) {  //上个命令完成后，才从任务消息队列接收数据,或和上个命令相同，更新数据
        smg_data = smg_data_now;
        if (smg_data_pre.cmd == disp_twinkleing) {
          etimer_stop(&et);
        }
        if (smg_data_now.cmd != disp_delay) {
          led_data[0] = smg_data.led[0];  //更新显示
          led_data[1] = smg_data.led[1];
          led_data[2] = smg_data.led[2];
          led_data[3] = smg_data.led[3];
          led_data[4] = smg_data.led[4];
        }
      }

      if (smg_data.cmd == disp_time) {  //显示时间
        smg_data.cmd = dispcmd_none;
      } else if (smg_data.cmd == disp_notwinkle) {  //显示长亮
        if (smg_data.count != 0xff) {
          smg_data.count--;
        }
        if (smg_data.count == 0) {
          Model = Model_Call;
          if (smg_data.timeout_handle != NULL) {
            smg_data.timeout_handle();
          } else {
            smg_data.cmd = dispcmd_none;
            menu_index = 1;
            entermenu.ctrl = ctrl_none;
          }
        }
      } else if (smg_data.cmd == disp_twinkle) {  //闪烁显示一位
        etimer_set(&et, 1);
        twinkle = 0;
        smg_data.cmd = disp_twinkleing;
        for (uint8_t i = 0; i < 5; i++) {
          if (smg_data.index == i) {
            led_data[i] = 0x00;
          } else {
            led_data[i] = smg_data.led[i];
          }
        }
      } else if (smg_data.cmd == disp_num) {  //显示号码
        smg_data.count--;
        if (dispnum_flag == disp_nocall_num) {
          if (get_callnum_cnt() > 0) {
            if (dispnum->cnt == 0) {
              dispnum = memb_dispnum_alloc();
            }
            dispnum->slave.Val = disp_num_cur;
            dispnum->time = 4;
            dispnum->cnt = Slave_Cur->cnt - 1;
            if (remove_find_dispnum(dispnum->slave.Val)) {
            }
            push_dispnum(dispnum);

            smg_data.count = 0;
          }
        }
        if (smg_data.count == 0) {
          if (get_callnum_cnt() > 0) {
            Slave_Cur = get_cur_num();

            if (Slave_Cur->is_disp == 0) {
              static sVoiceCmd voice;
              static uint16_t voice_value = 0;
              voice_value = Slave_Cur->slave.Val;
              voice.cmd = voicecmd_playcall;
              voice.value = (uint16_t*)&voice_value;
              process_start(&VoicePlay_Process, (process_data_t)&voice);
              Slave_Cur->is_disp = 1;
              set_curf_num(Slave_Cur);
            } else {
              memb_numcall_free(Slave_Cur);
              smg_data.count = 1;
              continue;
            }

            Slave_Cur->cnt--;
            if (Slave_Cur->cnt > 0) {
              if (remove_find_dispnum(Slave_Cur->slave.Val)) {
              } else {
                dispnum = memb_dispnum_alloc();
              }
              dispnum->slave.Val = Slave_Cur->slave.Val;
              dispnum->time = 6;
              dispnum->cnt = Slave_Cur->cnt;
              add_dispnum(dispnum);
            }

            led_data[0] = 0x00;
            led_data[1] = NumDis[Slave_Cur->slave.Val % 1000 / 100];
            led_data[2] = NumDis[Slave_Cur->slave.Val % 100 / 10];
            led_data[3] = NumDis[Slave_Cur->slave.Val % 10 / 1];
            led_data[4] = 0x00;
            disp_num_cur = Slave_Cur->slave.Val;
            smg_data.count = Slave_Cur->time;

            dispnum_flag = disp_call_num;
          } else if (get_dispnum_cnt() > 0) {
            dispnum = get_dispnum();
            led_data[0] = 0x00;
            led_data[1] = NumDis[dispnum->slave.Val % 1000 / 100];
            led_data[2] = NumDis[dispnum->slave.Val % 100 / 10];
            led_data[3] = NumDis[dispnum->slave.Val % 10 / 1];
            led_data[4] = 0x00;
            disp_num_cur = dispnum->slave.Val;
            smg_data.count = dispnum->time;

            if (dispnum->cnt < (remind_max - 1)) {
              dispnum->cnt--;
            }
            if (dispnum->cnt > 0) {
              dispnum->time = 6;
              add_dispnum(dispnum);
            } else {
              memb_dispnum_free(dispnum);
            }

            dispnum_flag = disp_nocall_num;
          } else {
            smg_data.cmd = disp_cmdfinish;
            menu_index = 1;
            entermenu.ctrl = ctrl_none;
            led = Led_DevInit;
            HAL_RTCEx_RTCEventCallback(NULL);
            process_start(&DispLed_Process, (process_data_t)&led);
            dispnum_flag = disp_none_num;
          }
        }
      } else if (smg_data.cmd == disp_cmdfinish) {
        smg_data.cmd = dispcmd_none;
        menu_index = 0;
        entermenu.ctrl = ctrl_none;
        static TIMEDATE_TypeDef htimedate = {0};
        TimeDate_CountTime(&htimedate);
        led_data[0] = NumDis[htimedate.Hours % 100 / 10];
        led_data[1] = NumDis[htimedate.Hours % 10 / 1];
        led_data[2] = NumDis[htimedate.Minutes % 100 / 10];
        led_data[3] = NumDis[htimedate.Minutes % 10 / 1];
        led_data[4] = ~led_data[4];
      } else if (smg_data.cmd == disp_delay) {
        if (smg_data_pre.cmd == smg_data.cmd) {  //相当于延时一个周期
          led_data[0] = smg_data.led[0];
          led_data[1] = smg_data.led[1];
          led_data[2] = smg_data.led[2];
          led_data[3] = smg_data.led[3];
          led_data[4] = smg_data.led[4];
          smg_data.count--;
          if (smg_data.count == 0) {
            smg_data.cmd = dispcmd_none;
            menu_index = 1;
            entermenu.ctrl = ctrl_none;
          }
        }
      } else if (smg_data.cmd == disp_factory) {
        static uint8_t flag = 0;
        if (flag == 0) {
          flag = 1;
          led_data[0] = NumDis[0x10];
          led_data[1] = NumDis[0x10];
          led_data[2] = NumDis[0x10];
          led_data[3] = NumDis[0x10];
          led_data[4] = 0xff;
        } else {
          flag = 0;
          led_data[0] = 0x00;
          led_data[1] = 0x00;
          led_data[2] = 0x00;
          led_data[3] = 0x00;
          led_data[4] = 0x00;
        }
      }
      smg_data_pre = smg_data;  //更新上一次操作
    } else if (ev == PROCESS_EVENT_TIMER) {
      smg_data.count--;
      if (twinkle == 1) {  //闪烁时，将对应位置0
        for (uint8_t i = 0; i < 5; i++) {
          if (smg_data.index == i) {
            led_data[i] = 0x00;
          } else {
            led_data[i] = smg_data.led[i];
          }
        }
        twinkle = 0;
      } else {
        led_data[smg_data.index] = smg_data.led[smg_data.index];
        twinkle = 1;
      }
      if (smg_data.count == 0) {
        Model = Model_Call;
        smg_data.cmd = dispcmd_none;
        menu_index = 0;
        entermenu.ctrl = ctrl_none;
        smg_data_pre = smg_data;
        etimer_stop(&et);
      } else {
        etimer_set(&et, 500);
      }
    }
  }

  PROCESS_END();
}

void disconnecttimeout_callback(void* parm) {
  if (disconn_disp_flag == 0) {
    LED_Display(RGB_Init);
    disconn_disp_flag = 1;
  } else {
    LED_Display(RGB_None);
    disconn_disp_flag = 0;
  }
  ctimer_reset(&c_disconnect);
}

PROCESS(DispLed_Process, "DispLed");
PROCESS_THREAD(DispLed_Process, ev, data) {
  static uint8_t led = Led_None;
  static struct etimer et;

  PROCESS_BEGIN();

  if (ev == PROCESS_EVENT_INIT) {
    led = *((uint8_t*)data);
    if (led == Led_None) {
      LED_Display(RGB_None);
      //			etimer_set(&et, 500);
      //			PROCESS_WAIT_EVENT_UNTIL(ev ==
      // PROCESS_EVENT_TIMER); 			LED_Display(RGB_None);
    } else if (led == Led_DevInit) {
      LED_Display(RGB_Init);
      //			etimer_set(&et, 500);
      //			PROCESS_WAIT_EVENT_UNTIL(ev ==
      // PROCESS_EVENT_TIMER); 			LED_Display(RGB_Init);
    } else if (led == Led_DevWifi) {
      //			LED_Display(RGB_DevWifi);
      //			etimer_set(&et, 2*CLOCK_SECOND);
      //			PROCESS_WAIT_EVENT_UNTIL(ev ==
      // PROCESS_EVENT_TIMER); 			LED_Display(RGB_None);
    } else if (led == Led_DevGsm) {
      LED_Display(RGB_DevGsm);
    } else if (led == Led_DevSingle) {
      LED_Display(RGB_DevSingle);
    } else if (led == Led_Call) {
      LED_Display(RGB_Call);
    } else if (led == Led_ClearCall) {
      LED_Display(RGB_ClearCall);
    } else if (led == Led_SetOk) {
      LED_Display(RGB_SetOk);
      etimer_set(&et, 500);
      PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
      LED_Display(RGB_None);
      etimer_set(&et, 500);
      PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
      LED_Display(RGB_SetOk);
      etimer_set(&et, 500);
      PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
      LED_Display(RGB_Init);
    } else if (led == Led_SetNet) {
      LED_Display(RGB_SetNet);
	  ctimer_stop(&c_disconnect);
    } else if (led == Led_SetNetOk) {
      LED_Display(RGB_SetNetOk);
    } else if (led == Led_SetNetFailed) {
      LED_Display(RGB_Init);
	  ctimer_stop(&c_disconnect);
    } else if (led == Led_NoConnect) {
      disconn_disp_flag = 0;
      ctimer_set(&c_disconnect, 500, disconnecttimeout_callback, NULL);
    } else if (led == Led_Connect) {
      LED_Display(RGB_Init);
      ctimer_stop(&c_disconnect);
    }
  }

  PROCESS_END();
}
